#include "ADUWater.h"
#include "ADUConfig.h"
#include "ADUGameManager.h"
#include "ADUConstant.h"

//#define USE_POLYGON 1

Water::Water(int _count,float _height){

    int _numVer;

    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();
    float centerX = origin.x + visibleSize.width/2;
    float centerY = origin.y + visibleSize.height/2;

    mStartX = origin.x;
    mVerticesSpacing = visibleSize.width*1.2/_count;

    mNormal = b2Vec2(0,1);

    mWorld = GameManager::getInstance()->mWorld;


    mControllerDef = new b2BuoyancyControllerDef();
    mControllerDef->normal.Set(0,1.0f);
    mControllerDef->density = DENSITY_WATER;
    mControllerDef->offset = _height/PTM_RATIO;
    mControllerDef->useWorldGravity = true;
    mControllerDef->useDensity = true;
    mControllerDef->linearDrag = 0.0f;
    mControllerDef->angularDrag = 0.0f;

    mController = (b2BuoyancyController*)mWorld->CreateController(mControllerDef);

    mDrawer = DrawNode::create();

    mCount = _count;
    mHeight = _height;
#ifdef USE_POLYGON
    _numVer = 2+mCount;
#else
    _numVer = 2*mCount;
#endif

    mVertices = new Vec2[_numVer];
    mSpring= new Spring[mCount];


#ifdef USE_POLYGON
    for (int i = 2; i<_numVer;i++){
    	 mVertices[i] = Vec2(mStartX+(_numVer-i-1)*mVerticesSpacing,mHeight);
    	 mSpring[i-2].SetOriginPos(mVertices[i]);
    	 mSpring[i-2].SetId(i-2);
    }
    mVertices[0] = Vec2(mVertices[_numVer-1].x,mBottom);
    mVertices[1] = Vec2(mVertices[2].x,mBottom);

#else
    for (int i = 0; i<_numVer;i++){
        	if (i < mCount){
        		mVertices[i] = Vec2(mStartX+(i)*mVerticesSpacing,mHeight);
        		mSpring[i].SetOriginPos(mVertices[i]);
        		mSpring[i].SetId(i);
        	}
        	else{
        		mVertices[i] = Vec2(mVertices[i-mCount].x,mBottom);
        	}

        }
#endif
    mFilledColor = Color4F(0.69, 0.47, 0.8, 1.0);
    mBorderColor = Color4F(0.81, 0.66, 0.96, 1);
    GameManager::getInstance()->mWater = this;
}


void Water::IncreaseWaterHeight(float dh) {
    if(mHeight >= maxHeight) return;
	mHeight += dh;
	for (int i = 0; i < mCount; i++){
		mSpring[i].ChangeYSurface(mHeight);
		mSpring[i].IncreaseHeight(dh);
	}
    
    GameManager::getInstance()->setWaterHeight(mHeight/PTM_RATIO);

	mController->offset = mHeight/PTM_RATIO;
}

Water::~Water(){

}

void Water::AddBody(b2Body* body){
	mController->AddBody(body);
}

void Water::AddListener(b2BuoyancyMergeListener *listener){
    mController->setBuoyancyMergeListener(listener);
}

void Water::RemoveBody(b2Body* body){
	mController->RemoveBody(body);
}

void Water::Clear(){
	mController->Clear();
}

void Water::Splash(float speed,int id){
	mSpring[id].mSpeed = speed;
}

void Water::OnUpdate(float dt){

    int _numVer;

    IncreaseWaterHeight((dt*GameManager::getInstance()->gameLevel)/2);
    _numVer = 2 + mCount;

    for(int e = 0; e < mCount; e++){
       mSpring[e].OnUpdate(dt);
    }

    float lDeltas[mCount];
    float rDeltas[mCount];

    for (int i = 0; i < mCount; i++)
    {
        if (i > 0)
        {
        	lDeltas[i] = mSpread * (mSpring[i].mY - mSpring [i - 1].mY);
            mSpring[i - 1].mSpeed += 2*lDeltas[i];
        }
        if (i < mCount - 1)
        {
        	rDeltas[i] = mSpread * (mSpring[i].mY - mSpring [i + 1].mY);
            mSpring[i + 1].mSpeed += 2*rDeltas[i];
        }
    }

    for (int i = 0; i < mCount; i++)
    {
        if (i > 0){
        	mSpring[i - 1].mY += lDeltas[i];
        }
        if (i < mCount - 1){
        	mSpring[i + 1].mY += rDeltas[i];
        }
    }

#ifdef USE_POLYGON
    for (int i = 2; i<_numVer;i++){
    	mVertices[i] = mSpring[i-2].GetPos();
    }
    mDrawer->clear();
    mDrawer->drawPolygon(mVertices, _numVer, mFilledColor, 2.0f, mBorderColor);
#else
    for (int i = 0; i<mCount;i++){
            mVertices[i] = mSpring[i].GetPos();
        }

        mDrawer->clear();

        for (int i = 0; i < mCount-1 ; i++){
        	mDrawer->drawTriangle(mVertices[i],mVertices[i+mCount],mVertices[i+mCount+1],mFilledColor);
        	mDrawer->drawTriangle(mVertices[i+1],mVertices[i],mVertices[i+mCount+1],mFilledColor);
        }
#endif

}

DrawNode* Water::GetDrawer(){
    return mDrawer;
}

float Water::getHeight() const
{
	return mHeight;
}

